package com.jolink.omiis.wechat.outer;

import java.io.IOException;
import java.io.StringReader;
import java.util.concurrent.atomic.AtomicLong;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.jolink.omiis.wechat.inner.IOmiisMessager;
import com.jolink.omiis.wechat.message.type.MessageType;
import com.jolink.omiis.wechat.util.WeChatConfiguration;
import com.jolink.omiis.wechat.util.XmlParser;

@Controller
@RequestMapping("/wechat/receiver/")
public class WeChatMessageController extends AbstractWeChatController {
	private static Logger logger = LoggerFactory.getLogger(WeChatMessageController.class);

	private static AtomicLong messageRequestCounter = new AtomicLong();

	@Autowired
	private ThreadPoolTaskExecutor taskExecutor;

	// @Autowired
	// private WeChatContext context;

	@Autowired
	private IOmiisMessager messager;

	@RequestMapping(value = "{APPID}", method = RequestMethod.GET)
	public void get(@PathVariable String APPID, HttpServletRequest request, HttpServletResponse response) {
		logger.info("APPID：{}，接收到腾讯普通请求：{}，InstanceId：{}。", APPID, request.getParameterMap(), this.hashCode());
		try {
			String body = readBody(request);
			if (StringUtils.isEmpty(body)) {
				throw new RuntimeException("信息为空！");
			}
			StringReader sr = new StringReader(body);
			Document doc = XmlParser.str2Xml(sr);
			logger.info("APPID：{}，请求信息：{}，transfer2Xml={}。", body, doc.asXML());
			String ret = "success";
			logger.info("采用异步处理消息策略，响应腾讯服务器内容：{}。", ret);
			response.getWriter().write(ret);
			response.getWriter().flush();
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			try {
				response.getWriter().write("");
			} catch (IOException e1) {
				logger.error(e.getMessage(), e);
			}
			return;
		}
	}

	@RequestMapping(value = "{APPID}", method = RequestMethod.POST)
	public void post(@PathVariable String APPID, HttpServletRequest request, HttpServletResponse response) {
		long t1 = System.currentTimeMillis();
		logger.info("APPID：{}，接收到腾讯普通信息请求：{}，InstanceId：{}，CharacterEncoding：{}。", APPID, request.getParameterMap(),
				this.hashCode(), request.getCharacterEncoding());
		String requestBody = null;
		String responseMessage = "success";
		try {
			response.setHeader("Cache-Control", "no-cache");
			response.setHeader("Prama", "no-cache");
			response.setContentType("text/xml;charset=UTF-8");
			response.setCharacterEncoding("UTF-8");
			requestBody = readBody(request);
			if (StringUtils.isEmpty(requestBody)) {
				throw new RuntimeException("腾讯微信用户发送信息为空！");
			}
			String decryptMsg = decrypt(request.getParameterMap(), requestBody);
			// 此处代码是为了全网发布 update by wangyq 2016-10-26
			boolean isReleaseTest = WeChatConfiguration.getIngleton().getBoolean("OMIIS_IS_RELEASE_TEST");
			boolean isSync = false;
			if (isReleaseTest) {
				logger.info("进入全网发布测试");
				Document msgDoc = XmlParser.str2Xml(decryptMsg);
				Element toUserNameE = (Element) msgDoc.selectSingleNode("/xml/ToUserName");
				String toUserName = toUserNameE.getTextTrim();
				Element fromUserNameE = (Element) msgDoc.selectSingleNode("/xml/FromUserName");
				String fromUserName = fromUserNameE.getTextTrim();
				Element createTimeE = (Element) msgDoc.selectSingleNode("/xml/CreateTime");
				String createTime = createTimeE.getTextTrim();
				if ("gh_3c884a361561".equals(toUserName)) {
					Element msgTypeE = (Element) msgDoc.selectSingleNode("/xml/MsgType");
					String msgType = msgTypeE.getTextTrim();
					if ("event".equals(msgType)) {
						Element eventE = (Element) msgDoc.selectSingleNode("/xml/Event");
						String event = eventE.getTextTrim();
						if (MessageType.LOCATION.toString().equals(event)) {
							Element rootElement = DocumentHelper.createElement("xml");
							Document rspDoc = DocumentHelper.createDocument(rootElement);
							rootElement.addElement("FromUserName").setText(toUserName);
							rootElement.addElement("ToUserName").setText(fromUserName);
							rootElement.addElement("CreateTime").setText(createTime);
							rootElement.addElement("MsgType").setText("text");
							rootElement.addElement("Content").setText(event + "from_callback");
							logger.info("全网测试返回内容（原）：{}。", rspDoc.asXML());
							ICrypt crypt = new Crypt(getContext().getCompentInfo().get("token"),
									getContext().getCompentInfo().get("encrypt_key"),
									getContext().getCompentInfo().get("app_id"));
							responseMessage = crypt.encrypt(rspDoc.asXML(), request.getParameter("timestamp"),
									request.getParameter("nonce"));
						}
					} else if ("text".equals(msgType)) {
						Element contentE = (Element) msgDoc.selectSingleNode("/xml/Content");
						String content = contentE.getTextTrim();
						if (content.contains("QUERY_AUTH_CODE")) {
							isSync = true;
						} else {
							Element rootElement = DocumentHelper.createElement("xml");
							Document rspDoc = DocumentHelper.createDocument(rootElement);
							rootElement.addElement("FromUserName").setText(toUserName);
							rootElement.addElement("ToUserName").setText(fromUserName);
							rootElement.addElement("CreateTime").setText(createTime);
							rootElement.addElement("MsgType").setText(msgType);
							rootElement.addElement("Content").setText(content + "_callback");
							logger.info("全网测试返回内容（原）：{}。", rspDoc.asXML());
							ICrypt crypt = new Crypt(getContext().getCompentInfo().get("token"),
									getContext().getCompentInfo().get("encrypt_key"),
									getContext().getCompentInfo().get("app_id"));
							responseMessage = crypt.encrypt(rspDoc.asXML(), request.getParameter("timestamp"),
									request.getParameter("nonce"));
						}
					}
				}
				logger.info("全网发布测试，响应腾讯服务器的返回内容：{}。", responseMessage);
			}

			// IMessageHandler messageHandler =
			// createMessageHandler(request.getParameterMap(), requestBody);
			// wr = messageHandler.handleMessage();
			// logger.info("请求信息处理完成，返回内容：{}。", GsonUtil.obj2Json(wr));
			// logger.info("返回处理结果：{}", wr.getResponseMsg());

			logger.info("开始异步处理请求信息，请求信息：{}，解密后信息：{}，响应腾讯服务器内容：{}。", requestBody, decryptMsg, responseMessage);
			if (!isReleaseTest || isSync) {
				taskExecutor.execute(new MessageWorker(getContext(), request.getParameterMap(), requestBody, messager));
			}
			// int contentLength = wr.getResponseMsg().trim().length();
			// response.setHeader("Content-Length",
			// String.valueOf(contentLength));
			// response.getWriter().write(wr.getResponseMsg().trim());
			response.getWriter().write(responseMessage);
			response.flushBuffer();
			response.getWriter().flush();
			response.getWriter().close();
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
			try {
				response.getWriter().write("");
			} catch (IOException e1) {
				logger.error(e.getMessage(), e);
			}
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			try {
				response.getWriter().write("");
			} catch (IOException e1) {
				logger.error(e.getMessage(), e);
			}
		}
		long t2 = System.currentTimeMillis();
		logger.info("处理腾讯普通信息请求完成，已接收消息数：{}，耗时：{}毫秒。", messageRequestCounter.incrementAndGet(), (t2 - t1));
	}
}
